
#ifndef _TW_VECTOR3D_H_
#define _TW_VECTOR3D_H_
#pragma once

 


class TwVector3d : public D3DXVECTOR3
{
public:

	//--------------------------------------------------
	// Creators...
	//--------------------------------------------------

	TwVector3d(){};
	TwVector3d(const TwVector3d& vec):D3DXVECTOR3(vec.x, vec.y, vec.z){};
	TwVector3d(float _x, float _y, float _z):D3DXVECTOR3(_x,_y,_z){};
	TwVector3d(TwVector2d _xy, float _z):D3DXVECTOR3(_xy.x, _xy.y, _z){};
	TwVector3d(const D3DXVECTOR3& vec):D3DXVECTOR3(vec.x, vec.y, vec.z){};
	~TwVector3d(void){};

	//--------------------------------------------------
	// Operators...
	//--------------------------------------------------

	// aliases
	TwVector2d& vec2() {return *((TwVector2d*)this);}
	operator TwVector2d& () {return vec2();}

	const TwVector2d& vec2()const {return *((TwVector2d*)this);}
	operator const TwVector2d&()const {return vec2();}

	const TwVector3d& operator *= (const TwVector3d& vec);
	const TwVector3d& operator /= (const TwVector3d& vec);
	const TwVector3d& operator *= (float v);
	const TwVector3d& operator /= (float v);

	const TwVector3d& operator += (const TwVector3d& vec);
	 

	//--------------------------------------------------
	// Mutators...
	//--------------------------------------------------

	void set(float _x, float _y, float _z);
	void clear(void);
	void setToAbsoluteValue();
	void invert();
	void negate();

	//--------------------------------------------------
	// Calculations\Operations...
	//--------------------------------------------------

	// testing operations
	float maxValue()const;
	float minValue()const;
	bool isClear()const;

	// length and distance calculations
	void normalize();
	float length()const;
	float lengthSquared()const;
	float distance(const TwVector3d& vec)const;
	float distanceSquared(const TwVector3d& vec)const;

	// dot and cross product
	float dotProduct(const TwVector3d& vec)const;
	void crossProduct(const TwVector3d& vec_b);
	void crossProduct(const TwVector3d& vec_a, const TwVector3d& vec_b);

	// angle operations (only valid for float, normalized versions)
	void computeHeadingAndPitch(float& heading, float& pitch)const;
	void setFromHeadingAndPitch(float heading, float pitch);
	void computeSphericalCoords(float& longitude, float& latitude)const;
	void setFromSphericalCoords(float longitude, float latitude);

	// reflect against the normal of a plane
	void reflect(const TwVector3d& normal);
	void reflect(const TwVector3d& source, const TwVector3d& normal);

	// refract through the normal of a plane
	void refract(const TwVector3d& normal, float incident, float transmitted);
	void refract(const TwVector3d& source, const TwVector3d& normal, float incident, float transmitted);

	// project along a normal vector
	void project(const TwVector3d& normal);
	void project(const TwVector3d& source, const TwVector3d& normal);

	// linear interpretation (integer scale from 0-100, float scale from 0-1)
	void twlerp(const TwVector3d& source_b, float scale);
	void twlerp(const TwVector3d& source_a, const TwVector3d& source_b, float scale);

	// create a normal to a plane given three points in clockwise order
	void createNormal(const TwVector3d& a, const TwVector3d& b, const TwVector3d& c);

	// create a normal given two vectors in clockwise order
	void createNormal(const TwVector3d& a, const TwVector3d& b);

	// test whether the vector is in the positive half-space of a normal
	bool testPositiveHalfSpace(const TwVector3d& normal)const;

	// compare with another vector using an optional epsilon value
	bool comparePosition(const TwVector3d& source)const;
	bool comparePosition(const TwVector3d& source, float epsilon)const;
	bool compareLength(const TwVector3d& source)const;
	bool compareLength(const TwVector3d& source, float epsilon)const;
	bool compareDirection(const TwVector3d& source)const;
	bool compareDirection(const TwVector3d& source, float epsilon)const;
	bool compareToZero()const;
	bool compareToZero(float epsilon)const;

	// set to the lesser components of two inputs
	void setMinByValue(const TwVector3d& source_b);
	void setMinByValue(const TwVector3d& source_a, const TwVector3d& source_b);
	// set to the lesser of two inputs (using length)
	void setMinByLength(const TwVector3d& source_b);
	void setMinByLength(const TwVector3d& source_a, const TwVector3d& source_b);

	// set to the greater components of two inputs
	void setMaxByValue(const TwVector3d& source_b);
	void setMaxByValue(const TwVector3d& source_a, const TwVector3d& source_b);
	// set to the greater of two inputs (using length)
	void setMaxByLength(const TwVector3d& source_b);
	void setMaxByLength(const TwVector3d& source_a, const TwVector3d& source_b);
};
#endif